/*
 *  Copyright (C) 2010 Jonathan MERCIER <bioinfornatics@fedoraproject.org>
 * 
 *  JACoMode is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  JACoMode is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with JACoMode.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.ubdx1.jacomode.models;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * @author Jonathan MERCIER <bioinfornatics@fedoraproject.org>,Louise-Amélie SCHMITT <louise-amelie.schmitt@etu.u-bordeaux1.fr>,Florence Maurier <florence_maurier@orange.fr>,Marianne Dussart <marianne.dussart@orange.fr>,Nicolas Fontaine <nifontaine@gmail.com>
 */
public final class Tools
{
    private static File        directory       = new File("/tmp/");
    /**
     * Compress a directory.
     * @param bzipFileName
     * @param directoryName
     * @throws InterruptedException if an error of interruption occurs
     * @throws IOException if an I/O error occurs
     */
    public static void compress(String bzipFileName, String directoryName) throws  IOException, InterruptedException
    {
        if (bzipFileName.indexOf(".tar.bz2") == -1)
        {
            bzipFileName += ".tar.bz2";
        }

        if (directoryName.contains(directory.getAbsolutePath()+"/"))
        {
            directoryName = directoryName.replace(directory.getAbsolutePath()+"/", "");
        }

        final ProcessBuilder processus  = new ProcessBuilder("/bin/tar", "cjf", bzipFileName, directoryName);
        processus.directory(directory);
        Process p = processus.start();
//      InputStream err = p.getErrorStream();
        InputStream out = p.getInputStream();
        BufferedReader input = new BufferedReader( new InputStreamReader(out) );
        String line = "";
        while ( ( line = input.readLine() ) != null)
        {
            System.out.println(line);

        }
        input.close();
        p.waitFor();
    }

    /**
     * Decompress a compressed file.
     * @param bzipFileName
     * @param directoryName
     * @throws InterruptedException if an error of interruption occurs
     * @throws IOException if an I/O error occurs
     */
    public static void decompress(String bzipFileName, String directoryName) throws  IOException, InterruptedException
    {
        // Uncompress
        final ProcessBuilder processus  = new ProcessBuilder("/bin/tar", "xjf", bzipFileName);
        processus.directory(new File(directoryName));
        Process p = processus.start();
//      InputStream err = p.getErrorStream();
        InputStream out = p.getInputStream();
        BufferedReader input = new BufferedReader( new InputStreamReader(out) );
        String line = "";
        while ( ( line = input.readLine() ) != null)
        {
            System.out.println(line);

        }
        input.close();
        p.waitFor();
    }

    /**
     * Move a file.
     * @param source
     * @param destination
     * @return a boolean informing on the moving result
     */
    public static boolean move(File source, File destination)
    {
        if( ! destination.exists() )
        {
            // Try renameTo
            boolean result = source.renameTo(destination);
            if( !result )
            {
                    // Try copy
                    result = true;
                    result &= copy(source,destination);
                    result &= source.delete();

            }
            return(result);
        }
        else
        {
            //If file exist cancel job
            return(false);
        }
    }

    /**
     * Copy a directory.
     * @param source
     * @param destination
     * @return a boolean informing on the copying status
     */
    public static boolean copy( File source, File destination )
    {
        boolean resultat = false;

        java.io.FileInputStream sourceFile      = null;
        java.io.FileOutputStream destinationFile= null;

        try
        {
            // Create file :
            destination.createNewFile();

            // Open stream
            sourceFile = new java.io.FileInputStream(source);
            destinationFile = new java.io.FileOutputStream(destination);

            // Read segment by 0.5Mo
            byte buffer[]=new byte[512*1024];
            int nbLecture;

            while( (nbLecture = sourceFile.read(buffer)) != -1 )
            {
                destinationFile.write(buffer, 0, nbLecture);
            }
            resultat = true;
        }
        catch( java.io.FileNotFoundException f )
        {

        }
        catch( java.io.IOException e )
        {

        }
        finally
        {
            try
            {
                sourceFile.close();
            }
            catch(Exception e) { }
            try
            {
                destinationFile.close();
            }
            catch(Exception e) { }
        }
        return( resultat );
    }

    /**
     * Delete a directory or a file.
     * @param path
     * @throws IOException if an I/O error occurs
     */
    public static void recursiveDelete(File path) throws IOException
    {
        if (!path.exists())
        {
            throw new IOException("File not found '" + path.getAbsolutePath() + "'");
        }
        if (path.isDirectory())
        {
            File[] children = path.listFiles();
            for (int i=0; children != null && i<children.length; i++)
            {
                recursiveDelete(children[i]);
            }
            if (!path.delete())
            {
                throw new IOException("No delete path '" + path.getAbsolutePath() + "'");
            }
        }
        else if (!path.delete())
        {
            throw new IOException("No delete file '" + path.getAbsolutePath() + "'");
        }
    }

    /**
     * Returns a list containing the files of a directory.
     * @param path
     * @throws IOException if an I/O error occurs
     * @return an ArrayList of files
     */
    public static ArrayList<File> listFileInDirectory(File path) throws IOException
    {
        ArrayList<File> fileInDirectory= new ArrayList<File>();

        if (!path.exists())
        {
            throw new IOException("File not found '" + path.getAbsolutePath() + "'");
        }
        if (path.isDirectory())
        {
            File[] children = path.listFiles();
            for (int i=0; children != null && i<children.length; i++)
            {
                listFileInDirectory(children[i]);
            }

        }
        else
        {
            fileInDirectory.add(path);
        }

        return fileInDirectory;
    }

    /**
     * Returns a list containing the files of a directory.
     * @param path
     * @param motif
     * @throws IOException if an I/O error occurs
     * @return an ArrayList of files
     */
    public static ArrayList<File> listFileInDirectory(File path, String motif) throws IOException
    {
        ArrayList<File> fileInDirectory= new ArrayList<File>();
        ArrayList<File> tmp= new ArrayList<File>();

        if (!path.exists())
        {
            throw new IOException("File not found '" + path.getAbsolutePath() + "'");
        }
        if (path.isDirectory())
        {
            File[] children = path.listFiles();
            for (int i=0; children != null && i<children.length; i++)
            {
                tmp = listFileInDirectory(children[i], motif);
                Iterator iterator = tmp.iterator();
                while(iterator.hasNext())
                {
                    fileInDirectory.add((File) iterator.next());
                }
            }

        }
        else
        {
            if (path.getName().endsWith(motif))
            {
                fileInDirectory.add(path);
            }
            else
            {
                // do nothing
            }
        }

        return fileInDirectory;
    }

}
